package com.zhkj.crawl.rank;

import com.zhkj.crawl.config.AmzSiteParamEnum;
import com.zhkj.crawl.config.Constants;
import com.zhkj.crawl.config.FetchRankException;
import com.zhkj.crawl.config.OkHttpPool;
import com.zhkj.crawl.config.jsoup.TrustSsl;
import com.zhkj.crawl.service.impl.ChromeService;
import com.zhkj.crawl.utils.UserAgentGen;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Connection;
import org.jsoup.HttpStatusException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

import java.io.IOException;
import java.net.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

@Slf4j
public class BaseService {
    public static final int MAX_RETRY = 4;
    public static final int MAX_RETRY_404 = 4;
    // ck存储 key是去参url
    public static Map<String, Map<String, String>> ckJar = new ConcurrentHashMap<>();

    // 证书信任 & 代理账密
    static {
        TrustSsl.trust();
        System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
        Authenticator.setDefault(new Authenticator() {
            public PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(Constants.PROXY_USERNAME, Constants.PROXY_PASSWORD.toCharArray());
            }
        });
    }

    /**
     * 查看当前代理的ip
     */
    public static void showIp(){
        try {
            System.out.printf("当前IP: %s\n", Jsoup.connect(Constants.URL_IP).proxy(OkHttpPool.get()).ignoreContentType(true).get().body().text());
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static Document seleniumGet(String url, Integer deep){
//        String waitCondition = "#prodDetails@@#detailBulletsWrapper_feature_div";
//        return ChromeService.go(url, 15, waitCondition);

        return ChromeService.go(url);
    }

    /**
     * jsoup发送get请求
     * 网络错误重试 ck携带
     * @param url
     * @param deep
     * @return
     */
    public static Document jsoupGet(String url, Integer deep){
        String key = getCksKey(url);
        Map<String, String> cks = ckJar.getOrDefault(key, new HashMap<>());
        Proxy proxy = OkHttpPool.get();
        try {
            Connection.Response response = Jsoup.connect(url)
                    .method(Connection.Method.GET)
                    .header("content-type", "text/html;charset=UTF-8")
                    .header("user-agent", UserAgentGen.gen())
                    .header("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9")
                    .header("sec-ch-ua-mobile", "?0")
                    .header("upgrade-insecure-requests", "1")
                    .header("sec-fetch-site", "none")
                    .header("sec-fetch-mode", "navigate")
                    .header("sec-fetch-user", "?1")
                    .header("sec-fetch-dest", "document")
                    .header("accept-encoding", "gzip, deflate, br")
                    .header("accept-language", "zh-CN,zh;q=0.9")
                    .header("sec-ch-ua", " \" Not;A Brand\";v=\"99\", \"Google Chrome\";v=\"91\", \"Chromium\";v=\"91\"")
//                    .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8888)))

                    .cookies(cks)
                    .proxy(proxy)
                    .timeout(15 * 1000)
                    .ignoreContentType(true).execute();

            cks.putAll(response.cookies());
            ckJar.put(key, cks);

            return response.parse();
        }catch (IOException e){
            ++deep;
            if(e instanceof HttpStatusException && deep >= MAX_RETRY_404) {
                HttpStatusException e1 = (HttpStatusException) e;
                if(e1.getStatusCode() == 404){
                    throw new FetchRankException(e1, FetchRankException.Type.INVALID, url);
                }
            }

            // 5: 2/4
            if(deep % 2 == 0){
                OkHttpPool.switchIp();
            }
            if(deep <= MAX_RETRY){
                log.info("<{}>网络错误{}，重试 {}", url, e.getMessage(), deep);
                return jsoupGet(url, deep);
            }
            throw new RuntimeException(String.format("重试%s次仍失败,跳过<%s>", deep, url), e);
        }
    }

    private static String getCksKey(String url){
        String key = url.split("\\?")[0];
        try {
            URI uri = new URI(url);
            String host = uri.getHost();
            if(host.contains("amazon")){
                key = host;
            }
            //... other strategy
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        return key;
    }

    public static void sleep(int sec){
        try {
            TimeUnit.SECONDS.sleep(sec);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    @Data
    public static class ProductDetail{
        private String itemId;
        private String url;
        private AmzSiteParamEnum siteParam;
        private String cateUrl;
        private String keyword;
        private String rank;
        private String rating;
        private String star;
        private Element element;

        public ProductDetail(String itemId) {
            this.itemId = itemId;
        }
    }
}
